/**
 * 
 */
package com.huxi.lang.utils;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;

/**
 * 对象构造工具类
 * 
 * @since 1.0
 * @version 1.0
 * @author jian.wu
 */
public abstract class BuilderUtils {

	public static <K> Set<K> setof(K[] values) {
		LinkedHashSet<K> set = new LinkedHashSet<>();
		for (K vv : values) {
			set.add(vv);
		}
		return set;
	}

	public static <K> Set<K> setof(Collection<? extends K> values) {
		HashSet<K> set = new HashSet<>();
		set.addAll(values);
		return set;
	}

	public static <K> Set<K> setof(K value) {
		HashSet<K> set = new HashSet<>();
		set.add(value);
		return set;
	}

	/**
	 * 向哈希表追加多个哈希项
	 * 
	 * @param <K>    哈希表键类型
	 * @param <V>    哈希表值类型
	 * @param map    哈希表，非空。
	 * @param entrys 多哈希项列表，有效数据如下: <br>
	 *               [K,V,K,V,...,Entry<K,V>,...,K,V,...]
	 * @return 直接返回参数哈希表
	 * @throws ClassCastException 哈希键或哈希值类型转换失败
	 * @since 1.0
	 * @version 1.0
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static <K, V> Map<K, V> appendAll(Map<K, V> map, Object... entrys) throws ClassCastException {
		Objects.requireNonNull(map);
		int len = entrys != null ? entrys.length : 0;
		for (int i = 0; i < len; i++) {
			Object k = entrys[i];
			if (k == null) {
				throw new ClassCastException("entrys arguments K[" + i + "] must be not null");
			}
			if (k instanceof Entry) {
				Object mk = ((Entry) k).getKey();
				Object mv = ((Entry) k).getValue();
				map.put((K) mk, (V) mv);
			} else {
				Object v = ++i < len ? entrys[i] : null;
				map.put((K) k, (V) v);
			}
		}
		return map;
	}

	/**
	 * 向哈希表追加多个哈希项
	 * 
	 * @param <K>    哈希表键类型
	 * @param <V>    哈希表值类型
	 * @param map    哈希表，非空。
	 * @param entrys 多哈希项列表
	 * @return 直接返回参数哈希表
	 * @since 1.0
	 * @version 1.0
	 */
	@SuppressWarnings("unchecked")
	public <K, V> Map<K, V> appendAll(Map<K, V> map, Entry<V, K>... entrys) {
		Objects.requireNonNull(map);
		int len = entrys != null ? entrys.length : 0;
		for (int i = 0; i < len; i++) {
			Entry<V, K> item = entrys[i];
			K k = item.getValue();
			if (k != null) {
				map.put(k, item.getKey());
			}
		}
		return map;
	}

	/**
	 * 创建哈希表
	 * 
	 * @param <K>    哈希表键类型
	 * @param <V>    哈希表值类型
	 * @param key    首个哈希项键，非空。
	 * @param value  首个哈希项值
	 * @param entrys 多哈希项列表，有效数据如下: <br>
	 *               [K,V,K,V,...,Entry<K,V>,...,K,V,...]
	 * @return 哈希表，非空。
	 * @throws ClassCastException 哈希键或哈希值类型转换失败
	 * @since 1.0
	 * @version 1.0
	 * @see #appendAll(Map, Object...)
	 */
	public static <K, V> Map<K, V> mapof(K key, V value, Object... entrys) throws ClassCastException {
		Objects.requireNonNull(key);
		HashMap<K, V> map = new HashMap<>();
		map.put(key, value);
		return appendAll(map, entrys);
	}

	/**
	 * 创建哈希表
	 * 
	 * @param <K> 哈希表键类型
	 * @param <V> 哈希表值类型
	 * @param map 来源哈希表
	 * @return 新建哈希表
	 * @since 1.0
	 * @version 1.0
	 * @see #appendAll(Map, Entry...)
	 */
	public static <K, V> Map<K, V> mapof(Map<V, K> map) {
		HashMap<K, V> mm = new HashMap<>();
		if (map != null) {
			return appendAll(mm, map.values());
		}
		return mm;
	}

	/**
	 * 查询目标类注释
	 * 
	 * @param <T>
	 * @param target  目标类
	 * @param anClass 注释类型
	 * @param inherit 注释类型是否可继承父类或接口申明
	 * @return 首个满足条件注释，未发现则返回空值。
	 * @since 1.0
	 * @version 1.0
	 */
	public static <T extends Annotation> T findAnnotation(Class<?> target, Class<T> anClass, boolean inherit) {
		if (target != null) {
			T an = target.getAnnotation(anClass);
			if (an != null || !inherit) {
				return an;
			}
			final Class<?>[] interfaces = target.getInterfaces();
			for (final Class<?> i : interfaces) {
				an = findAnnotation(i, anClass, true);
				if (an != null) {
					return an;
				}
			}
			target = target.getSuperclass();
			if (!(target == null || target.getName().startsWith("java."))) {
				return findAnnotation(target, anClass, true);
			}
		}
		return null;
	}
}
